package stardust.product.platform.webc.container;


import javax.servlet.ServletContext;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.support.WebApplicationContextUtils;
import stardust.product.platform.webc.WebcCallback;
import stardust.product.platform.webc.WebcConfig;
import stardust.product.platform.webc.WebcException;
import stardust.product.platform.webc.WebcFilter;
import stardust.product.platform.webc.WebcResourceReference;


public class ApplicationContextContainer extends WebcContainer
{

  private ApplicationContext applicationContext;

  public ApplicationContextContainer(WebcConfig config)
  {
    super(config);
    this.applicationContext = this.getApplicationContext();
  }

  public ApplicationContextContainer(WebcConfig config, ServletContext servletContext)
  {
    this(config);
    this.applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
  }

  private ApplicationContext getApplicationContext()
  {
//    return ContextLoaderListener.getCurrentWebApplicationContext();
    return ContextLoader.getCurrentWebApplicationContext();
  }
  
  protected <T> T defineBean(Class<T> targetClass)
  {
    T instance = null;

    try
    {
      instance = this.applicationContext.getBean(targetClass);
    }
    catch (NoSuchBeanDefinitionException ex)
    {
      if (this.applicationContext instanceof AbstractApplicationContext)
      {
        AbstractApplicationContext appContext;
        BeanDefinitionRegistry beanDefinitionRegistry;
  
        appContext = (AbstractApplicationContext) this.applicationContext;
        beanDefinitionRegistry = (BeanDefinitionRegistry) appContext.getBeanFactory();
        
        if (!appContext.containsBean(targetClass.getName()))
        {
          beanDefinitionRegistry.registerBeanDefinition(targetClass.getName(),
                                                        BeanDefinitionBuilder.genericBeanDefinition(targetClass).getBeanDefinition());
        }
        
        instance = appContext.getBean(targetClass);
      }
      else
      {
        throw new WebcException("无法向Spring注册Bean定义[" + targetClass.getName() + "]。");
      }
    }

    return instance;
  }

  public void registerHandler(String uri, WebcResourceReference entry)
  {
    entry.setInstance(this.defineBean(entry.getTargetClass()));
    super.registerHandler(uri, entry);
  }
  
  public void registerFilter(Class<? extends WebcFilter> filterClass)
  {
    super.registerFilter(this.defineBean(filterClass));
  }
  
  public void registerCallback(Class<? extends WebcCallback> callback)
  {
    super.registerCallback(this.defineBean(callback));
  }

}
